#pragma GCC diagnostic ignored "-fpermissive"

#include <allegro.h>
#include <iostream>
#include "actorManager.h"
#include "stageManager.h"
#include "game.h"
#include "controlManager.h"
#include "collisionManager.h"

//funcion y variable global que cuentan los ticks del timer para mantener la velocidad el juego.
void tick_count();
volatile int tick;

void tick_count(){
    tick++;
}
END_OF_FUNCTION(tick_count);

/*Constructor de game, inicializa allegro, el timer,
 *protege las variables globales y pone en null a los managers
 */
Game::Game(){
    allegro_init();
    install_keyboard();
    actor_manager=NULL;
    stage_manager=NULL;
    control_manager=NULL;
    collision_manager=NULL;
    install_timer();
    LOCK_VARIABLE(tick); // protege la variable
    LOCK_FUNCTION(tick_count); // protege procedimiento
    install_int(&tick_count, 14); // instala interrupción
}

/*Desctructor de la clase*/
Game::~Game(){
}

/*Inicializa la clase game, inicializa el modo grafico y crea los managers*/
void Game::init(int gfx_mode, int w, int h, int col){
    //register_png_file_type();

    set_color_depth(col);
    if (set_gfx_mode(gfx_mode,w, h, 0,0)<0){
        shutdown("No se pudo inicializar modo grafico");
        return;
    }

    create_actormanager();
    create_stagemanager();
    create_controlmanager();
    start();
}

/*Destruye los managers y cierra allegro*/
void Game::shutdown(std::string message="Gracias por jugar"){
    if (actor_manager) delete actor_manager;
    if (stage_manager) delete stage_manager;
    if (control_manager) delete control_manager;
    if (collision_manager) delete collision_manager;

    set_gfx_mode(GFX_TEXT,0,0,0,0);
    std::cout << name << std::endl;
    std::cout << message << std::endl;
    allegro_exit();
}

/*Crea un ActorManager*/
void Game::create_actormanager(){
    actor_manager = new ActorManager(this);
}

/*Crea un StageManager*/
void Game::create_stagemanager(){
    stage_manager = new StageManager(this, gfx_w, gfx_h);
}

/*Crea un ControlManager*/
void Game::create_controlmanager(){
    control_manager = new ControlManager();
}

void Game::create_collisionmanager(){
    collision_manager = new CollisionManager(this);
}
/*Inicia el juego*/
void Game::start(){
    actual_tick=tick; // se alinea con el timer real
    old_tick=tick;
    max_frame_skip=15; // estable el salto de cuadro por defecto
    main();
    shutdown();
}

/*ejecuta el juego mientras no se presione la tecla ESC*/
void Game::main(){
    while (!key[KEY_ESC]);
}

/*Setea el nombre del juego*/
void Game::set_name(std::string n){
    name=n;
}

/*Retorna el nombre del juego*/
std::string Game::get_name(){
    return name;
}

/*Ciclo del juego, actualiza los managers y realiza el control de velocidad del juego*/
void Game::update(){
    if (actual_tick<=tick){
        actor_manager->update(); // ciclo lógico
        // Comprobación para collision_manager
        if (collision_manager) collision_manager->update();
        // Coprobación para control_manager
        if (control_manager) control_manager->update();
        actual_tick++;
    }

    if ((actual_tick>=tick) || (frame_skip>max_frame_skip)){
        stage_manager->update(); // ciclo gráfico
        if (frame_skip>max_frame_skip) actual_tick=tick;
        graphic_tick++;
        frame_skip=0;
    }
    else{
        frame_skip++;
    }

    //Imprime en pantalla la cantidad de FPS
    if (tick-old_tick >=70){ // se cumplió un segundo
        rectfill(screen,0,0,200,14,0); // borrar el antigüo marcador
        textprintf_ex(screen, font, 0,0, makecol(0, 0, 255), -1, "fps: %u frameskip:%u", graphic_tick, frame_skip);
        graphic_tick=0;
        old_tick=tick;
    }
}

/*Setea el maximo de frame skip*/
void Game::set_max_frame_skip(int max_fs){
    max_frame_skip=max_fs;
}
